package com.netmi.myuploadfileretrofit;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.sdk.android.vod.upload.VODSVideoUploadCallback;
import com.alibaba.sdk.android.vod.upload.VODSVideoUploadClient;
import com.alibaba.sdk.android.vod.upload.VODSVideoUploadClientImpl;
import com.alibaba.sdk.android.vod.upload.VODUploadCallback;
import com.alibaba.sdk.android.vod.upload.model.SvideoInfo;
import com.alibaba.sdk.android.vod.upload.session.VodHttpClientConfig;
import com.alibaba.sdk.android.vod.upload.session.VodSessionCreateInfo;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import com.hw.videoprocessor.VideoProcessor;
import com.hw.videoprocessor.util.VideoProgressListener;
import com.netmi.myuploadfileretrofit.bean.FileUrlEntity;
import com.netmi.myuploadfileretrofit.bean.VideoDataBean;
import com.netmi.myuploadfileretrofit.http.HttpReqeustInterceptor;
import com.netmi.myuploadfileretrofit.inteface.ReqProgressCallBack;
import com.netmi.myuploadfileretrofit.inteface.RetrofitUploadFile;
import com.netmi.myuploadfileretrofit.utils.Fileutils;
import com.netmi.myuploadfileretrofit.utils.PermissionUtil;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

import static com.netmi.myuploadfileretrofit.utils.FileUtil.getDataColumn;
import static com.netmi.myuploadfileretrofit.utils.FileUtil.isDownloadsDocument;
import static com.netmi.myuploadfileretrofit.utils.FileUtil.isExternalStorageDocument;
import static com.netmi.myuploadfileretrofit.utils.FileUtil.isMediaDocument;

public class MainActivity extends AppCompatActivity {
    private static final String DEFAULT_MEDIA_URI =
            "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv";

    private static String TAG = "tgw" + MainActivity.class.getSimpleName();
    public static int SELECT_VIDEO_REQUEST_CODE = 100;
    public static String BASE_URL = "https://yijia-api-test.yijiabo.net/";
    private static String token = "wPTFFknECXlOEphnj9-deTeNWuKtMGvQ";

    String videoPath = null; //本地地址
    Uri contentUri  = null;//本地视频URI地址
    String videoUrl = null; //上传后的地址
    private Button btSelectVideo, btSelectImage, btPlayVideo, btUploadVideo,btVideoCompress,btDownVideo;
    private TextView tvAddress;
    private ProgressBar progressBar;

    //设置EXOplayer播放参数
    //1.默认的播放View
    private PlayerView playerView;
    //2.您可以ExoPlayer使用创建实例ExoPlayerFactory。工厂提供了一系列方法来创建ExoPlayer具有不同
    //级别自定义的实例。对于绝大多数用例，ExoPlayerFactory.newSimpleInstance应该使用其中一种 方法。
    //这些方法返回SimpleExoPlayer
    private SimpleExoPlayer player = null;
    // Produces DataSource instances through which media data is loaded.--生成加载媒体数据的数据源实例。
    private DataSource.Factory dataSourceFactory = null;
    // This is the MediaSource representing the media to be played.---这是表示要播放的媒体的媒体源
    private MediaSource videoSource = null;


    //设置阿里云上传，这部分暂时废弃
    private VODSVideoUploadClient uploader = null;
    VodHttpClientConfig vodHttpClientConfig = null;
    VodSessionCreateInfo vodSessionCreateInfo = null;
    VODUploadCallback callback = null;
    String uploadAuth = "";
    private static String accessKeyId = "8C17a7KHludNpQFJ";
    private static String accessKeySecret = "VygVO1luFJwIWDZE0KvTC0lWNmRD49";

    //  Retrofit 上传
    Retrofit retrofit = null;
    OkHttpClient okHttpClient = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btSelectVideo = findViewById(R.id.bt_select_video);
        btPlayVideo = findViewById(R.id.bt_start_play_video);
        btUploadVideo = findViewById(R.id.bt_start_upload_video);
        btSelectImage = findViewById(R.id.bt_select_image);
        btVideoCompress = findViewById(R.id.bt_start_compress);

        progressBar = findViewById(R.id.progress_bar);
        tvAddress = findViewById(R.id.tv_video_address);
        btDownVideo = findViewById(R.id.bt_download_video);

        playerView = findViewById(R.id.player_view);
        creatVideoPlayer(MainActivity.this);
        addPlayerListener();

        //阿里云，暂时未使用废弃
//        initALiCloudUpload();

        videoPath = DEFAULT_MEDIA_URI;

        btSelectVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //请求权限
                PermissionUtil.requirePermissions(MainActivity.this, PermissionUtil.PERMISSION_TYPE_IMPORTANT, new PermissionUtil.RequirePermissionDialogListener() {
                    @Override
                    public void onSuccess() {
                        startSelectVideo();
                    }

                    @Override
                    public void onFailure(String tips) {
                        Toast.makeText(MainActivity.this, "你需要存储权限才能使用", Toast.LENGTH_SHORT).show();
                        return;
                    }
                });

            }
        });

        btSelectImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //请求权限
                PermissionUtil.requirePermissions(MainActivity.this, PermissionUtil.PERMISSION_TYPE_IMPORTANT, new PermissionUtil.RequirePermissionDialogListener() {
                    @Override
                    public void onSuccess() {
                        startSelectImage();
                    }

                    @Override
                    public void onFailure(String tips) {
                        Toast.makeText(MainActivity.this, "你需要存储权限才能使用", Toast.LENGTH_SHORT).show();
                        return;
                    }
                });

            }
        });
        btPlayVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (player != null && !TextUtils.isEmpty(videoPath)) {
                    Intent intent = new Intent(MainActivity.this,PlayVideoActivity.class);
                    intent.putExtra("videoPath",videoPath);
                    startActivity(intent);
                    player.setPlayWhenReady(true);//控制播放暂停开始
                } else {
                    Toast.makeText(MainActivity.this, "选择视频后才能播放", Toast.LENGTH_SHORT).show();
                }
            }
        });

        btUploadVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                if (TextUtils.isEmpty(videoPath)) {
//                    Toast.makeText(MainActivity.this, "选择文件后才能上传", Toast.LENGTH_SHORT).show();
//
//                } else {
//                  initALiCloudUpload(); 有问题
                    initRetrofit();


//                }
            }
        });

        btVideoCompress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TextUtils.isEmpty(videoPath)) {
                    Toast.makeText(MainActivity.this, "选择文件后才能压缩", Toast.LENGTH_SHORT).show();

                } else {
//                    compressVideo("/storage/emulated/0/Android/data/com.netmi.myuploadfileretrofit/files/Movies/videoCompress/1594449351808.mp4",MainActivity.this);
                  compressVideo(videoPath,MainActivity.this);

                }
            }
        });


        btDownVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                if (TextUtils.isEmpty(videoUrl)) {
//                    Toast.makeText(MainActivity.this, "上传文件后才能下载", Toast.LENGTH_SHORT).show();
//
//                } else {
                    Intent intent = new Intent(MainActivity.this,DownloadVideoActivity.class);
                    intent.putExtra("videoPath",videoUrl);
                    startActivity(intent);
//                }
            }
        });
    }

    private void initRetrofit() {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(getOkHttpClient())
                .addConverterFactory(GsonConverterFactory.create()) //gson转换器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        MultipartBody.Part filePart = multiPartFiles(videoPath);

        RetrofitUploadFile retrofitUploadFile = retrofit.create(RetrofitUploadFile.class);
        //3使用rxjava的方式
//        Observable<FileUrlEntity> observable = retrofitUploadFile.uploadFiles(filePart);
//        observable.compose(RxSchedulers.compose())
//                .subscribe(new Observer<FileUrlEntity>() {
//                    @Override
//                    public void onSubscribe(Disposable d) {
//
//                    }
//
//                    @Override
//                    public void onNext(FileUrlEntity fileUrlEntity) {
//                        Log.d(TAG, "onNext: 上传完成地址" + fileUrlEntity.getData().getUrl());
//                    }
//
//                    @Override
//                    public void onError(Throwable e) {
//                        Log.d(TAG, "onError: 失败" + e.getMessage());
//                    }
//
//                    @Override
//                    public void onComplete() {
//                        Log.d(TAG, "onComplete: 上传完成地址");
//                    }
//                });

        //原retrofit
        retrofit.create(RetrofitUploadFile.class)
                .uploadFiles(filePart).enqueue(new Callback<FileUrlEntity>() {
            @Override
            public void onResponse(Call<FileUrlEntity> call, retrofit2.Response<FileUrlEntity> response) {
                if (!TextUtils.isEmpty(response.body().getData().getUrl())){
                    Log.d(TAG, "onResponse: 上传完成地址不为空：" + response.body().getData().getUrl());
                    videoUrl = response.body().getData().getUrl();
                }else {
                    Log.d(TAG, "onResponse: 上传完成地址" + response.body().toString());

                }

            }

            @Override
            public void onFailure(Call<FileUrlEntity> call, Throwable t) {
                Log.d(TAG, "onResponse: 失败" + call.toString() + "--" + t.getMessage().toString());

            }
        });
    }

    private OkHttpClient getOkHttpClient() {

        if (okHttpClient == null) {
            synchronized (MainActivity.class) {
                if (okHttpClient == null) {
                    okHttpClient = new OkHttpClient.Builder()
                            .connectTimeout(15, TimeUnit.SECONDS)
                            .hostnameVerifier(new HostnameVerifier() {
                                @Override
                                public boolean verify(String hostname, SSLSession session) {
                                    return true;
                                }
                            }).addInterceptor(new HttpReqeustInterceptor(new ReqProgressCallBack() {
                                @Override
                                public void onProgress(long currentSize, long contentLength) {
                                    Log.d(TAG, "onProgress: 监听上传进度bytesWritten:"+currentSize+"总长度contentLength:"+contentLength);
                                }
                            },token)).build();
                }
            }
        }
        return okHttpClient;
    }


    private void initALiCloudUpload() {
        // create VODUploadClient
        uploader = new VODSVideoUploadClientImpl(this.getApplicationContext());
        uploader.init();

        //2.构建上传参数
//参数请确保存在，如不存在SDK内部将会直接将错误throw Exception
// 文件路径保证存在之外因为Android 6.0之后需要动态获取权限，请开发者自行实现获取"文件读写权限".
        vodHttpClientConfig = new VodHttpClientConfig.Builder()
                .setMaxRetryCount(2)//重试次数
                .setConnectionTimeout(15 * 1000)//连接超时
                .setSocketTimeout(15 * 1000)//socket超时
                .build();
        //构建短视频VideoInfo,常见的描述，标题，详情都可以设置
        SvideoInfo svideoInfo = new SvideoInfo();
        svideoInfo.setTitle(new File(videoPath).getName());//标题
        svideoInfo.setDesc("");//文件详情
        svideoInfo.setCateId(1);//分类id
        //构建点播上传参数(重要)
        vodSessionCreateInfo = new VodSessionCreateInfo.Builder()
                .setVideoPath(videoPath)//视频地址
                .setAccessKeyId(accessKeyId)//临时accessKeyId
                .setAccessKeySecret(accessKeySecret)//临时accessKeySecret
                .setSecurityToken(token)//securityToken
                .setExpriedTime("2020-7-15")//STStoken过期时间
//                .setRequestID(requestID)//requestID，开发者可以传将获取STS返回的requestID设置也可以不设.
                .setIsTranscode(true)//是否转码.如开启转码请AppSever务必监听服务端转码成功的通知
                .setSvideoInfo(svideoInfo)//短视频视频信息
                .setVodHttpClientConfig(vodHttpClientConfig)//网络参数
                .build();


        uploader.uploadWithVideoAndImg(vodSessionCreateInfo, new VODSVideoUploadCallback() {
            @Override
            public void onUploadSucceed(String videoId, String imageUrl) {
                //上传成功返回视频ID和图片URL.
                Log.d(TAG, "onUploadSucceed" + "videoId:" + videoId + "imageUrl" + imageUrl);
            }

            @Override
            public void onUploadFailed(String code, String message) {
                //上传失败返回错误码和message.错误码有详细的错误信息请开发者仔细阅读
                Log.d(TAG, "onUploadFailed" + "code" + code + "message" + message);
            }

            @Override
            public void onUploadProgress(long uploadedSize, long totalSize) {
                //上传的进度回调,非UI线程
                Log.d(TAG, "onUploadProgress" + uploadedSize * 100 / totalSize);
                long progress = uploadedSize * 100 / totalSize;
//                handler.sendEmptyMessage(0);
            }

            @Override
            public void onSTSTokenExpried() {
                Log.d(TAG, "onSTSTokenExpried");
                //STS token过期之后刷新STStoken，如正在上传将会断点续传
                uploader.refreshSTSToken(accessKeyId, accessKeySecret, token, "500");
            }

            @Override
            public void onUploadRetry(String code, String message) {
                //上传重试的提醒
                Log.d(TAG, "onUploadRetry" + "code" + code + "message" + message);
            }

            @Override
            public void onUploadRetryResume() {
                //上传重试成功的回调.告知用户重试成功
                Log.d(TAG, "onUploadRetryResume");
            }
        });
    }


    private void addPlayerListener() {
        // 注册播放器监听
        player.addListener(new Player.EventListener() {
            @Override
            public void onTimelineChanged(Timeline timeline, @Nullable Object manifest, int reason) {
                String content = "当时间轴和/或清单被刷新时调用。\n" +
                        "注意，如果时间轴发生了变化，那么位置不连续也可能发生。例如，由于从时间轴中添加或删除了句点，当前句点索引可能已经更改。这将不会通过对onPositionDiscontinuity(int)的单独调用报告。\n" +
                        "参数:时间轴-最新的时间轴。永远不要为空，但可能是空的。\n" +
                        "舱单-最新的舱单。可能是null。\n" +
                        "原因-玩家。TimelineChangeReason负责此时间线更改。";
                Log.d("tgw", "onTimelineChanged: i=" + reason + "发生情况" + content);
            }

            @Override
            public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                String content = "默认的void onTracksChanged(TrackGroupArray trackGroups，\n" +
                        "TrackSelectionArray trackSelections)\n" +
                        "当可用轨道或选定轨道发生更改时调用。\n" +
                        "参数:trackGroups—可用的曲目。决不为空，但长度可能为零。\n" +
                        "trackselection——每个渲染器的轨迹选择。决不为空，且长度始终为Player.getRendererCount()，但可能包含空元素。";
                Log.d("tgw", "onTracksChanged: " + content);
            }

            @Override
            public void onLoadingChanged(boolean isLoading) {

                String content = "当播放器开始或停止加载源文件时调用。\n" +
                        "参数:isLoading—当前是否正在加载源文件。";
                Log.d("tgw", "onLoadingChanged: isLoading" + isLoading + "---" + content);
            }

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                //Player.STATE_IDLE：这是初始状态，播放器停止时的状态以及播放失败时的状态。
                //Player.STATE_BUFFERING：玩家无法立即从当前位置进行游戏。这主要是因为需要加载更多数据。
                // Player.STATE_READY：玩家可以立即从当前位置进行游戏。
                //Player.STATE_ENDED：播放器播放完所有媒体。
                String content = "当从Player.getPlayWhenReady()或Player.getPlaybackState()返回的值发生更改时调用。\n" +
                        "参数:播放时准备-是否播放将继续时准备。\n" +
                        "状态常量之一。";
                Log.d("tgw", "onPlayerStateChanged: playWhenReady" + playWhenReady + "---playbackState:" + playbackState + "---" + content);
            }

            @Override
            public void onRepeatModeChanged(int repeatMode) {
                String content = "当Player.getRepeatMode()的值发生更改时调用。\n" +
                        "参数:重复模式-播放器。用于回放的重复模式。";
                Log.d("tgw", "onRepeatModeChanged: repeatMode" + repeatMode + "---" + content);

            }

            @Override
            public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
                String content = "当Player.getShuffleModeEnabled()的值发生更改时调用。\n" +
                        "参数:shuffleModeEnabled -是否启用窗口的改组。";
                Log.d("tgw", "onShuffleModeEnabledChanged: shuffleModeEnabled" + shuffleModeEnabled + "---" + content);

            }

            @Override
            public void onPlayerError(ExoPlaybackException error) {
                String content = "默认空onPlayerError(外部playbackexception错误)\n" +
                        "发生错误时调用。播放状态将转换到播放器。调用此方法后立即执行STATE_IDLE。player实例仍然可以使用，如果不再需要player .release()，则仍然必须调用它。\n" +
                        "参数:错误-错误。";
                Log.d("tgw", "onPlayerError: error" + error + "---" + content);

            }

            @Override
            public void onPositionDiscontinuity(int reason) {
                String content = "当位置不连续而不更改时间轴时调用。一段位置不连续发生在当前窗口或指数变化(由于回放过渡时间表从一个时期到下一个),或者当回放位置跳跃在正在播放(作为寻求执行的结果,或当源引入了内部不连续)。\n" +
                        "位置不连续是由于位置的变化而发生的";
                Log.d("tgw", "onPositionDiscontinuity: reason" + reason + "---" + content);

            }

            @Override
            public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
                String content = "当当前回放参数更改时调用。回放参数可能会由于调用player . setplaybackparameters (PlaybackParameters)而更改，或者播放器本身也可能更改这些参数(例如，如果音频回放切换到直通模式，则不再可能进行速度调整)。\n" +
                        "参数:播放参数-播放参数。";
                Log.d("tgw", "onPlaybackParametersChanged: playbackParameters" + playbackParameters + "---" + content);

            }

            @Override
            public void onSeekProcessed() {
                String content = "当玩家处理完所有挂起的请求后调用。在向onPlayerStateChanged(boolean, int)报告了对播放器状态的任何必要更改之后，保证会发生这种情况。";
                Log.d("tgw", "onSeekProcessed: " + "---" + content);

            }
        });

    }


    private void startSelectVideo() {
        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, SELECT_VIDEO_REQUEST_CODE);
    }

    private void startSelectImage() {
        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, SELECT_VIDEO_REQUEST_CODE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SELECT_VIDEO_REQUEST_CODE && resultCode == RESULT_OK && null != data) {
            Uri selectedVideo = data.getData();
            String[] filePathColumn = {MediaStore.Video.Media.DATA};
            filePathColumn = new String[]{
                    MediaStore.Video.Media.DATA,
                    MediaStore.Video.Media.DURATION,
                    MediaStore.Video.Media._ID,
                    MediaStore.Video.Media.DISPLAY_NAME,
                    MediaStore.Video.Media.SIZE,
                    MediaStore.Video.Media.DATE_MODIFIED};
            Cursor cursor = MainActivity.this.getContentResolver().query(selectedVideo, filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            VideoDataBean videoDataBean = new VideoDataBean();
            String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
            long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID));
            Uri uri = Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id + "");
            long duration = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));
            String name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME));
            long size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));
            long date = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_MODIFIED));
            contentUri = ContentUris.withAppendedId(
                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
            videoDataBean.setPath(path);
            videoDataBean.setId(id);
            videoDataBean.setUri(uri);
            videoDataBean.setDuration(duration);
            videoDataBean.setName(name);
            videoDataBean.setSize(size);
            videoDataBean.setDate(date);
            Log.d(TAG, "onActivityResult: t文件大小：" + toFileSizeM(size + ""));

            Log.d(TAG, "onActivityResult: t文件详情：" + videoDataBean.toString());
            videoPath = cursor.getString(columnIndex);
            cursor.close();
            Log.d(TAG, "onActivityResult: 文件地址" + videoPath);
            tvAddress.setText("视频地址：" + videoPath);
//            prepareVideoSourse("/storage/emulated/0/Android/data/com.netmi.myuploadfileretrofit/files/Movies/videoCompress/1594449351808.mp4");
            prepareVideoSourse(videoPath,id);
        }
    }

    //压缩视频
    private void compressVideo(String videoPath, Activity activity) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                    retriever.setDataSource(videoPath);
                    int originWidth = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
                    int originHeight = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
                    int bitrate = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE));
                    Log.d(TAG, "compressVideo originWidth=" + originWidth + " originHeight==" + originHeight + " bitrate==" + bitrate);
                    String videoOutCompressPath = Fileutils.getVideoOutCompressPath(videoPath, activity);
                    VideoProcessor.processor(activity)
                            .input(videoPath)
                            .bitrate(bitrate / 3 )
                            .output(videoOutCompressPath)
                            .progressListener(new VideoProgressListener() {
                                @Override
                                public void onProgress(float progress) {
                                    int intProgress = (int) (progress * 100);
                                    Message message = mHandler.obtainMessage();
                                    message.what = 0;
                                    message.arg1 = intProgress;
                                    mHandler.sendMessage(message);
                                    if (intProgress == 100) {
                                        message.what = 1;
                                        message.obj = videoOutCompressPath;
                                        mHandler.sendMessage(message);
                                    }

                                }
                            })
                            .process();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private String getVideoOutCompressPath(String videoPath, Activity context) {
        String path = null;
        File file = null;
        long tag = System.currentTimeMillis();
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {//SDCard是否可用
            //最好把images替换成你的项目名称，避免有重复文件夹
            path = context.getExternalFilesDir(Environment.DIRECTORY_MOVIES) + File.separator + "videoCompress/";
            file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            Log.d(TAG, "compressVideo getVideoOutCompressPath--- getExternalFilesDir(Environment.DIRECTORY_MOVIES): " + context.getExternalFilesDir(Environment.DIRECTORY_MOVIES).getAbsolutePath());
            path = context.getExternalFilesDir(Environment.DIRECTORY_MOVIES) + File.separator + "videoCompress/" + tag + ".mp4";
        } else {
            Log.d(TAG, " compressVideo getVideoOutCompressPath---getFilesDir: " + context.getFilesDir().getAbsolutePath());
            path = context.getFilesDir() + File.separator + "videoCompress/";
            file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            path = context.getFilesDir() + File.separator + "videoCompress/" + tag + ".mp4";
        }
        Log.d(TAG, "compressVideo getVideoOutCompressPath---最终路径: " + path);

        return path;

    }

    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    Log.e(TAG, "compressVideo 压缩进度==" +msg.arg1);
                    progressBar.setProgress(msg.arg1);
                    break;
                case 1:

                    Toast.makeText(MainActivity.this, "压缩完成", Toast.LENGTH_SHORT).show();
                    String videoOutCompressPath = (String) msg.obj;
                    try {
                        Log.e(TAG, "compressVideo 压缩后大小==" + toFileSizeM("" + getFileSize(new File(videoOutCompressPath))));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
            return false;
        }
    });

    private static long getFileSize(File file) throws Exception {

        long size = 0;
        if (file.exists()) {
            FileInputStream fis = null;
            fis = new FileInputStream(file);
            size = fis.available();
        } else {
            file.createNewFile();
            Log.e("获取文件大小", "文件不存在!");
        }
        return size;
    }

    public static String toFileSizeM(String fileSizeKb) {
        String fileSizeM = "";
        if (fileSizeKb == null)
            fileSizeM = "0" + "B";
        long fSize = Long.valueOf(fileSizeKb);
        if (fSize < 1024) {
            fileSizeM = fileSizeKb + "B";//字节
        } else if (fSize > 1024) {
            BigDecimal bg = new BigDecimal(fSize);
            BigDecimal flsize = new BigDecimal(fSize);
            BigDecimal temp = new BigDecimal(1024);
            if (-1 == temp.compareTo(flsize) || 0 == temp.compareTo(flsize)) {
                //四色五入保留2位小数(根据需求随意调整)
                flsize = bg.divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP);
                fileSizeM = flsize + "KB";
            }
            if (-1 == temp.compareTo(flsize) || 0 == temp.compareTo(flsize)) { //MB
                //四色五入保留2位小数(根据需求随意调整)
                flsize = flsize.divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP);
                fileSizeM = flsize + "M";
            }
        }
        return fileSizeM;
    }

    public static MultipartBody.Part multiPartFiles(String filePath) {
        //转换类型，这三种上传图片时都可以用
        String type = "application/octet-stream";
//        type = "multipart/form-data";
//        type = "*/*";
        File file = new File(filePath);
        if (file.exists() && file.isFile()) {
            RequestBody requestBody = RequestBody.create(MediaType.parse(type), file);
            return MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        }
        return null;
    }

    private void creatVideoPlayer(Activity context) {
        player = new SimpleExoPlayer.Builder(context).build();
        // Bind the player to the view.
        playerView.setPlayer(player);
        // Produces DataSource instances through which media data is loaded.
        dataSourceFactory = new DefaultDataSourceFactory(context,
                Util.getUserAgent(context, "myuploadfileretrofit"));
    }

    public static Uri insertVideoIntoMediaStore(Context context, String fileName) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, fileName);
        contentValues.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());
        contentValues.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");

        Uri uri = context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
        return uri;
    }


    private void prepareVideoSourse(String videoAddress,long videoId) {
        //Android Q 及其以上 视频真实路径需要根据 id 拼接
        String path = MediaStore.Video.Media
                .EXTERNAL_CONTENT_URI
                .buildUpon()
                .appendPath(String.valueOf(videoId)).build().toString();
        if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.Q){
            videoAddress = path;
        }
        String URIString = getPath(MainActivity.this,contentUri);

        Log.d(TAG, "prepareVideoSourse视频预览路径: "+videoAddress);
        Log.d(TAG, "prepareVideoSourse视频预览URI路径: "+contentUri);
        Log.d(TAG, "prepareVideoSourse视频预览URI转文件路径: "+URIString);
        Uri mp4VideoUri = Uri.parse(videoAddress);
//        mp4VideoUri =insertVideoIntoMediaStore(MainActivity.this, videoAddress);
        mp4VideoUri =  contentUri;
        // This is the MediaSource representing the media to be played.
        videoSource =
                new ProgressiveMediaSource.Factory(dataSourceFactory)
                        .createMediaSource(mp4VideoUri);
        // Prepare the player with the source.
        player.prepare(videoSource);
        player.setPlayWhenReady(false);//控制播放暂停开始

    }

    /**
     * 专为Android4.4设计的从Uri获取文件绝对路径，以前的方法已不好使
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {

            //一些三方的文件浏览器会进入到这个方法中，例如ES
            //QQ文件管理器不在此列

            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

            }
            // MediaProvider
            else if (isMediaDocument(uri)) {

            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {// MediaStore (and general)
            return getDataColumn(context, uri, null, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {// File

        }
        return null;
    }
}
